# -*- coding: latin-1 -*-

# Required Google App Engine Imports
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext.webapp import template
from google.appengine.api import urlfetch

# Specific local imports
import os
import thread
from XMLParser import XMLParser
import youtubeAPI
from ascii import latin1_to_ascii

# Allow for 'real' if-statements in the templates
webapp.template.register_template_library('smart_if')

class MainPage(webapp.RequestHandler):
    def getEmbeddedVideo(self, origArtistName, track):
        youtubeResult = self.ytd.getTopVideo(latin1_to_ascii(origArtistName) + ' ' + latin1_to_ascii(track['name']))
        if (youtubeResult):
            track['youtube'] = youtubeResult.GetSwfUrl()+'&theme=light&fs=0'
            self.youtube_songs.append(youtubeResult)
            self.expectedSongs = self.expectedSongs + 1;
            
    def get(self):
        xmlparser = XMLParser()
        self.expectedSongs = 0
        template_values = {}
        
        # Get the artist name from the searchBox text field
        artistName = self.request.get('searchBox')
        if artistName == "":
            # Redirect to the artist search if the user didn't enter anything
            self.redirect("/")
        try:
            # Get artists that match the search from the Last.fm API
            origArtistName = artistName
            artistName = artistName.replace(" ", "+")
            artistName = latin1_to_ascii(artistName)
            url = "http://ws.audioscrobbler.com/2.0/?method=artist.getinfo&autocorrect=1&api_key=01c6ba54dc9c0fba3f086b6830659197&artist=" + artistName
            result = urlfetch.fetch(url)
            artistInfoDoc = result.content
            artist_info_data = xmlparser.parse_artist_info(artistInfoDoc)
            
            # Replace the artist name with an auto-corrected one if there was one
            artistName = artist_info_data['name']
            origArtistName = artistName
            if (artistName):
                artistName = artistName.replace(" ", "+")
            else:
                raise urlfetch.Error
            
            # Add the artist to the list of artists that the user is currently browsing
            otherArtists = self.request.get('otherArtists')
            if otherArtists:
                if origArtistName not in otherArtists:
                    otherArtists = otherArtists + ','+origArtistName
            else:
                otherArtists = origArtistName
            artistList = otherArtists.split(',')
            
            # Get info for the matched artist
            url = "http://ws.audioscrobbler.com/2.0/?method=artist.search&autocorrect=1&api_key=01c6ba54dc9c0fba3f086b6830659197&artist=" + artistName
            result = urlfetch.fetch(url)
            artistSearchDoc = result.content
            artist_search_data = xmlparser.parse_artist_search(artistSearchDoc)
            
            # Get songs by that artist from Last.fm
            url = "http://ws.audioscrobbler.com/2.0/?method=track.search&autocorrect=1&api_key=01c6ba54dc9c0fba3f086b6830659197&track=" + artistName
            result = urlfetch.fetch(url)
            songSearchDoc = result.content
            song_search_data = xmlparser.parse_song_search(songSearchDoc)
            
            # Find YouTube videos of the top songs of the artist
            ytd = youtubeAPI.youtubeData()
            ytd.initializeAPI()
            self.ytd =ytd
            self.youtube_songs = []
            
            i = 0
            for track in song_search_data['tracks']:
                if i < 5:
                    thread.start_new_thread(self.getEmbeddedVideo, (origArtistName, track))
                i = i + 1
                
            while (len(self.youtube_songs) < self.expectedSongs):
                continue
            
            # Find artists related to all the artists the user is browsing
            recommendation = []
            
            url = "http://ws.audioscrobbler.com/2.0/?method=artist.getsimilar&autocorrect=1&api_key=01c6ba54dc9c0fba3f086b6830659197&artist=" + artistName
            result = urlfetch.fetch(url)
            artistSimilarDoc = result.content
            artist_similar_data = xmlparser.parse_get_similar(artistSimilarDoc)
            
            # This is a list of all the artists related to all the artists the user is currently browsing
            mega_list = []
            
            # Do a 'similar artist' search for every artist in the user's browsing list
            for artist in artistList:
                if artist != origArtistName:
                    url = "http://ws.audioscrobbler.com/2.0/?method=artist.getsimilar&autocorrect=1&api_key=01c6ba54dc9c0fba3f086b6830659197&artist=" + artist  .replace(' ', '+')
                    result = urlfetch.fetch(url)
                    artistSimilarDoc = result.content
                    new_artist_similar_data = xmlparser.parse_get_similar(artistSimilarDoc)
                    
                    for artist in new_artist_similar_data:
                        mega_list.append(artist['name'])
             
            # Recommend an artist if they are present in the large list, the current artist's similar list, and the match rating is above some arbitrary threshold       
            for artist in artist_similar_data:
                if ((artist['name'] in mega_list) and (artist['name'] not in artistList) and (artist['match'] > 0.35)):
                    recommendation.append(artist['name'])
                            
            
            # Place the picked-apart XML documents (as well as other data) and store them in key,value maps that we can use in our HTML templates
            template_values = {
            'artist_search': artist_search_data,
            'song_search'  : song_search_data, 
            'artist_info'  : artist_info_data,
            'youtube_info' : self.youtube_songs,
            'other_artists': otherArtists,
            'artist_list'  : artistList,
            'recommendation': recommendation
            }
        except urlfetch.Error:
            self.redirect("/error")
            
        # Render the HTML template for this page
        path = os.path.join(os.path.dirname(__file__), 'templates/index.html')
        self.response.out.write(template.render(path, template_values))

class ArtistSearch(webapp.RequestHandler):
    def get(self):
        path = os.path.join(os.path.dirname(__file__), 'templates/search.html')
        self.response.out.write(template.render(path, {}))
        
class ErrorPage(webapp.RequestHandler):
    def get(self):
        path = os.path.join(os.path.dirname(__file__), 'templates/nomatch.html')
        self.response.out.write(template.render(path, {}))

# Our application is made up of three pages:
# URL        Name
# ------------------------
# /          ArtistSearch
# /results   MainPage
# /error     ErrorPage
application = webapp.WSGIApplication([('/', ArtistSearch),('/results', MainPage),('/error', ErrorPage)], debug=True)


# Main just starts up the application
def main():
    run_wsgi_app(application)

if __name__ == "__main__":
    main()
